package com.boarsoft.boar.config.var.biz;

import com.boarsoft.boar.app.AppBiz;
import com.boarsoft.boar.config.entity.ConfigVar;
import com.boarsoft.boar.config.entity.ConfigVarApp;
import com.boarsoft.boar.config.entity.ConfigVarEnv;
import com.boarsoft.boar.config.var.ConfigVarBiz;
import com.boarsoft.boar.entity.AppInfo;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.common.util.StringUtil;
import com.boarsoft.hibernate.biz.SimpleBizImpl;
import org.apache.commons.lang.StringEscapeUtils;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

@Component("configVarBiz")
public class ConfigVarBizImpl extends SimpleBizImpl implements ConfigVarBiz {

	@Autowired
	private AppBiz appBiz;


	@Override
	@Transactional(readOnly = true)
	public ConfigVar get(String id) {
		return dao.get(ConfigVar.class, id);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public String add(ConfigVar a) {
		ConfigVar configVar=findByName(a.getAppId(),a.getName(),a.getVer());
		unactive(a.getAppId(),a.getName(),a.getVer());
		if(configVar!=null){
			configVar.setValue(a.getValue());
			configVar.setStatus((short) 1);
			dao.update(configVar);
			return configVar.getId();
		}
		a.setStatus((short) 1);
		dao.save(a);
		return a.getId();
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void unactive(String appId,String name,String ver) {
		String unactiveSql="update config_var v set v.tStatus=0 where v.cId in "
				+ "(select cVarId from config_var_app where cAppId ='%s') and v.vName='%s' and vVer!='%s'";
		dao.executeSql(String.format(unactiveSql,appId,name,ver));
	}

	@Override
	@Transactional
	public void update(ConfigVar a) {
		dao.merge(a);
	}

	@Override
	@Transactional(readOnly = true)
	public PagedResult<ConfigVar> list(String projId, String key, int pageNo, int pageSize, String orderBy) {
		StringBuffer sb = new StringBuffer();
		if (Util.strIsNotEmpty(projId)) {
			projId = StringEscapeUtils.escapeSql(projId);
			sb.append(" and projId = '").append(projId).append("'");
		}
		if (Util.strIsNotEmpty(key)) {
			key = StringEscapeUtils.escapeSql(key);
			sb.append(" and (name like '%").append(key);
			sb.append("%')");
		}
		int total = dao.getTotal(ConfigVar.class, sb.toString());
		if (Util.strIsNotEmpty(orderBy)) {
			String ob = Util.array2str(orderBy.split(","), ",");
			sb.append(" order by ").append(ob);
		} else {
			sb.append(" order by group, name");
		}
		List<ConfigVar> alt = dao.list(ConfigVar.class, sb.toString(), pageNo, pageSize);
		return new PagedResult<>(total, alt, pageNo, pageSize);
	}

	@Override
	@Transactional
	public void delete(String id) {
		dao.delete(ConfigVar.class, id);
		StringBuilder sb = new StringBuilder();
		sb.append("delete from ").append(ConfigVarApp.class.getName());
		sb.append(" where varId='").append(id).append("'");
		dao.executeUpdate(sb.toString());
	}

	@Override
	@Transactional(readOnly = true)
	public List<ConfigVar> list2(String appId, String env) {
		StringBuffer sb = new StringBuffer("select r.id,r.projId,r.group,r.name,r.memo,r.ver,r.status,e.value from ")
				.append(ConfigVar.class.getName())
				.append(" r,")
				.append(ConfigVarEnv.class.getName())
				.append(" e")
				.append(" where r.id  in (select o.varId from ")
				.append(ConfigVarApp.class.getName())
				.append(" o where o.appId = '")
				.append(appId)
				.append("')")
				.append(" and r.id = e.varId ")
				.append(" and (e.env = 'all' or e.env = '")
				.append(env)
				.append("') and r.status=1");
		List<Object[]> ls = dao.list(sb.toString());
		List<ConfigVar> lcf = new ArrayList<>();
		for (int i = 0; i < ls.size(); i++) {
			ConfigVar cf = new ConfigVar();
			Object[] ob = ls.get(i);
			cf.setId((String) ob[0]);
			cf.setProjId((String) ob[1]);
			cf.setGroup((String) ob[2]);
			cf.setName((String) ob[3]);
			cf.setMemo((String) ob[4]);
			cf.setVer((String) ob[5]);
			cf.setStatus((Short) ob[6]);
			cf.setValue((String) ob[7]);
			lcf.add(i,cf);
		}
		return lcf;
	}

	@Override
	@Transactional
	public PagedResult<ConfigVar> list2Env(String projId, String appId, String key, String env,int pageNo, int pageSize, String orderBy) {
		StringBuffer sb = new StringBuffer("select r.id,r.projId,r.group,r.name,r.memo,r.ver,r.status,e.value,e.env ");
		StringBuffer hsql=new StringBuffer("from ")
				.append(ConfigVar.class.getName()).append(" r,")
				.append(ConfigVarEnv.class.getName()).append(" e")
				.append(" where r.id = e.varId")
				.append(" and r.id in (select o.varId from ").append(ConfigVarApp.class.getName())
				.append(" o where o.appId = '").append(appId).append("')");
		if(StringUtil.isNotBlank(env)) {
			hsql=hsql.append(" and e.env = '").append(env).append("'");
		}
		if(StringUtil.isNotBlank(key)){
			hsql.append(" and r.name like '%").append(key).append("%'");
		}
		int total = dao.getTotal("select count(1) ".concat(hsql.toString()));
		AppInfo appInfo=appBiz.get(appId);
		List<Object[]> ls = dao.list(sb.append(hsql).toString(),pageNo, pageSize);
		List<ConfigVar> lcf = new ArrayList<>();
		for (int i = 0; i < ls.size(); i++) {
			ConfigVar cf = new ConfigVar();
			Object[] ob = ls.get(i);
			cf.setId((String) ob[0]);
			cf.setProjId((String) ob[1]);
			cf.setGroup((String) ob[2]);
			cf.setName((String) ob[3]);
			cf.setMemo((String) ob[4]);
			cf.setVer((String) ob[5]);
			cf.setStatus((Short) ob[6]);
			cf.setValue((String) ob[7]);
			cf.setEnv((String) ob[8]);
			cf.setAppId(appId);
			cf.setAppCode(appInfo.getCode());
			cf.setProjId(projId);
			lcf.add(i,cf);
		}
		return new PagedResult<>(total, lcf, pageNo, pageSize);
	}

	@Override
	@Transactional(readOnly = true)
	public List<ConfigVar> listWithoutEnv(String appId) {
		StringBuffer sb = new StringBuffer("select r.id,r.projId,r.group,r.name,r.memo,r.ver,r.status,r.value from ")
				.append(ConfigVar.class.getName())
				.append(" r ")
				.append(" where r.id in (select o.varId from ")
				.append(ConfigVarApp.class.getName())
				.append(" o where o.appId = '")
				.append(appId)
				.append("') and r.status=1");
		List ls = dao.list(sb.toString());
		List<ConfigVar> lcf = new ArrayList<>();
		for (int i = 0; i < ls.size(); i++) {
			ConfigVar cf = new ConfigVar();
			Object[] ob = (Object[])ls.get(i);
			cf.setId((String) ob[0]);
			cf.setProjId((String) ob[1]);
			cf.setGroup((String) ob[2]);
			cf.setName((String) ob[3]);
			cf.setMemo((String) ob[4]);
			cf.setVer((String) ob[5]);
			cf.setStatus((Short) ob[6]);
			cf.setValue((String) ob[7]);
			lcf.add(i,cf);
		}
		return lcf;
	}

	@Override
	@Transactional(readOnly = true)
	public List<ConfigVar> listAll() {
		StringBuffer sb = new StringBuffer("select r.id,r.projId,r.group,r.name,r.memo,r.ver,r.status,r.value from ")
				.append(ConfigVar.class.getName())
				.append(" r");
		List ls = dao.list(sb.toString());
		List<ConfigVar> lcf = new ArrayList<>();
		for (int i = 0; i < ls.size(); i++) {
			ConfigVar cf = new ConfigVar();
			Object[] ob = (Object[])ls.get(i);
			cf.setId((String) ob[0]);
			cf.setProjId((String) ob[1]);
			cf.setGroup((String) ob[2]);
			cf.setName((String) ob[3]);
			cf.setMemo((String) ob[4]);
			cf.setVer((String) ob[5]);
			cf.setStatus((Short) ob[6]);
			cf.setValue((String) ob[7]);
			lcf.add(i,cf);
		}
		return lcf;
	}

	@Override
	@Transactional(readOnly = true)
	public ConfigVar findByName(String appId, String name, String ver) {
		StringBuffer sb = new StringBuffer("select r.id,r.projId,r.group,r.name,r.memo,r.ver,r.status,r.value from ")
				.append(ConfigVar.class.getName())
				.append(" r ")
				.append(" where r.id in (select o.varId from ")
				.append(ConfigVarApp.class.getName())
				.append(" o where o.appId = '")
				.append(appId)
				.append("') and r.name = '")
				.append(name)
				.append("' and r.ver = '")
				.append(ver).append("'");
		List ls = dao.list(sb.toString());
		List<ConfigVar> lcf = new ArrayList<>();
		for (int i = 0; i < ls.size(); i++) {
			ConfigVar cf = new ConfigVar();
			Object[] ob = (Object[])ls.get(i);
			cf.setId((String) ob[0]);
			cf.setProjId((String) ob[1]);
			cf.setGroup((String) ob[2]);
			cf.setName((String) ob[3]);
			cf.setMemo((String) ob[4]);
			cf.setVer((String) ob[5]);
			cf.setStatus((Short) ob[6]);
			cf.setValue((String) ob[7]);
			lcf.add(i,cf);
		}
		if(lcf.size() == 0){
			return null;
		}
		if(lcf.size()>1){
			throw new RuntimeException("应用:["+appId+"],版本为["+ver+"]的参数["+name+"]不唯一，请联系管理员进行确认");
		}
		return lcf.get(0);
	}

	@Override
	@Transactional
	public void upd(ConfigVar configVar) {
		dao.update(configVar);
	}

	@Override
	@Transactional(readOnly = true)
	public List<ConfigVar> findByStatus(String projId, String name, short status) {
		StringBuffer sb = new StringBuffer("select r from ")//
				.append(ConfigVar.class.getName())//
				.append(" r where r.projId = :projId")//
				.append(" and r.status = :status")//
				.append(" and r.name = :name");
		Query<ConfigVar> q = dao.createQuery(ConfigVar.class, sb.toString());
		q.setParameter("projId", projId);
		q.setParameter("status", status);
		q.setParameter("name", name);
		return q.getResultList();
	}

}